<?php

//导入系统环境
require_once("../control/interface.php");

/*
系统公共数据处理类
*/

class libDataClass
{
	use control\interfaces;
	
	/**
	 * 管理员登录
	 *
	 * @param array $data
	 * @return array
	 */
	public function adLogin(array $data): array
	{
		if (empty($data['post']['userName'])) {
			$json['warn'] = "请输入用户名";
		} elseif (preg_match(checkString, $data['post']['userName']) == 0) {
			$json['warn'] = "用户名格式有误";
		} elseif (empty($data['post']['password'])) {
			$json['warn'] = "请输入登录密码";
		} elseif (strlen($data['post']['password']) < 6 || strlen($data['post']['password']) > 20) {
			$json['warn'] = "登录密码不得低于六位或大于20位";
		} elseif (empty($data['post']['prove'])) {
			$json['warn'] = "请输入验证码";
		} elseif ($data['post']['prove'] != $_SESSION["yan"]) {
			$json['warn'] = "验证码输入错误";
		} elseif (empty($data['post']['did'])) {
			$json['warn'] = "登录设备异常";
		} else {
			$password = $data['post']['password'];
			
			$user       = query("user", " userName = '" . $data['post']['userName'] . "' ");
			$adLoginNum = para("adLoginNum");//每日登录密码最大的错误次数
			/*if (empty($user['userName'])) {
				$json['warn'] = "用户名【" . $data['post']['userName'] . "】不存在";
			} else*/
			if ($user['loginError'] >= $adLoginNum and $user['loginErrorDay'] == date("Y-m-d")) {
				$json['warn'] = "您今天登录密码输入错误次数已经超过" . $adLoginNum . "次，不能再登录了";
			} elseif ($user['state'] == "停用") {
				$json['warn'] = "您的账号处于停用状态，请联系行政人员！";
			} //登录密码输入错误
			elseif (verifyPwd($password, $user['password']) !== true) {
				if (isset($_SESSION['forgetPas']) && $data['post']['userName'] == $_SESSION['forgetPas']['name'] and verifyPwd($password, $_SESSION['forgetPas']['prove'])) {
					//如果是点击忘记密码时发送到手机上的短信验证码
					update([
						"table" => "user",
						"field" => [
							"password"   => md5s($data['post']['password']),
							"updateTime" => date("Y-m-d H:i:s"),
						],
						"where" => " userName = '" . $data['post']['userName'] . "' ",
					]);
					unset($_SESSION['forgetPas']['prove']);
					$json['warn'] = 2;
				} else {
					if ($user['loginError'] >= $adLoginNum) {
						$user['loginError'] = 0;
					}
					$num    = (int) $user['loginError'] + 1;
					$remain = $adLoginNum - $num;//今天还能登录的次数
					update([
						"table" => "user",
						"field" => [
							"loginError"    => $num,
							"loginErrorDay" => date("Y-m-d"),
							"updateTime"    => date("Y-m-d H:i:s"),
						],
						"where" => " userName = '" . $data['post']['userName'] . "' ",
					]);
					$json['warn'] = "账号或密码错误，您今天还可以登录" . $remain . "次";
				}
			} else {
				$json['warn'] = 2;
			}
			if ($json['warn'] == 2) {
				$this->rSet($user['uid'] . 'loginPage', 1);
				//登录密码错误次数清零
				update([
					"table" => "user",
					"field" => [
						'deviceId'   => $data['post']['did'],
						'loginError' => 0,
					],
					"where" => " userName = '" . $data['post']['userName'] . "' ",
				]);
				//添加登录记录
				insert([
					"table" => "log",
					"field" => [
						"type" => "user",
						"stid" => $user['stid'],
						"text" => $user['name'] . "登录了管理员后台，ip地址：" . getIp(),
						"time" => date("Y-m-d H:i:s"),
					],
				]);
				//创建登录session，返回跳转地址
				$_SESSION['stid']     = $user['stid'];
				$_SESSION['deviceId'] = $data['post']['did'];
				$json['href']         = root . "control/adIndex.html";
			}
		}
		return $json;
	}
	
	/**
	 * 获取企业微信扫码登录参数
	 */
	public function getPara($data): array
	{
		return [
			'appid'   => para('qyWeChatCorpid'),
			'agentid' => para('qyWeChatQrAppId'),
			'url'     => urlencode(root . 'control/qyLoginClass.html?did=' . $data['post']['did']),
			'nonstr'  => self::getId(),
		];
	}
	
	/**N
	 * 短信验证码
	 *
	 * @param array $data
	 * @return array
	 */
	public function newProve(array $data): array
	{
		//赋值
		$tel     = $data['post']['tel']; //需要发送短信的手机号码
		$session = $_SESSION['prove'];   //保存到session中的验证信息
		$oldTime = $session['time'] + 60;//最后一次发送验证码的时间不得晚于此时间
		//判断并执行
		if (empty($tel)) {
			$json['warn'] = "请输入注册手机号码";
		} elseif (preg_match(checkTel, $tel) == 0) {
			$json['warn'] = "手机号码输入错误";
		} elseif ($oldTime > time() and $session['tel'] == $tel) {
			$json['warn'] = "发送验证码间隔不能超过一分钟";
		} else {
			$rand = rand(10000, 99999);
			//发送短信
			sms(array(
				"tel"           => $tel,
				"TemplateCode"  => "para('aliyunTemplateCode')",
				"TemplateParam" => array("code" => $rand),
			));
			//返回
			$_SESSION['prove'] = array("rand" => $rand, "time" => time(), "tel" => $tel);
			$json['warn']      = "发送成功";
		}
		return $json;
	}
	
	/**
	 * 重置密码
	 *
	 * @param array $data
	 * @return array
	 */
	public function adForgetPassword(array $data): array
	{
		//赋值
		$session = getVal($_SESSION, 'forgetPas');                       //防止重复发送短信的session
		$oldTime = (isset($session['time']) ? $session['time'] : 0) + 60;//最后一次发送验证码的时间不得晚于此时间
		//判断
		if (empty($data['post']['name'])) {
			$json['warn'] = "用户名不能为空";
		} elseif (preg_match(checkString, $data['post']['name']) == 0) {
			$json['warn'] = "用户名格式有误";
		} elseif ($oldTime > time() and $session['name'] == $data['post']['name']) {
			$json['warn'] = "发送验证码间隔不能低于一分钟";
		} else {
			$user = query("user", " userName = '" . $data['post']['name'] . "' ");
			if (empty($user['userName'])) {
				$json['warn'] = "用户名不存在";
			} elseif (empty($user['tel'])) {
				$json['warn'] = "此用户没有登记手机号码";
			} elseif (preg_match(checkTel, $user['tel']) == 0) {
				$json['warn'] = "此用户手机号码格式有误";
			} else {
				//生成随机六位短信验证码
				$prove = rand(100000, 999999);
				//发送短信
				sms([
					"tel"           => $user['tel'],
					"TemplateCode"  => para('aliyunTemplateCodeReset'),
					"TemplateParam" => ["code" => $prove],
				]);
				//返回
				$_SESSION['forgetPas'] = ["time" => time(), "name" => $data['post']['name'], "prove" => md5s($prove)];
				$json['warn']          = "发送成功";
			}
		}
		return $json;
	}
	
	/*根据省份获取下属城市下拉菜单内容值*/
	public function getCity($data)
	{
		$json['city'] = repeatSelect(array(
			"type"     => "option",
			"sqlForm"  => " region where province = '" . $data['post']['province'] . "' ",
			"sqlField" => "city",
			"name"     => "city",
			"title"    => "城市",
		));
		return $json;
	}
	
	/*根据省份和城市获取下属区域下拉菜单*/
	public function getArea($data)
	{
		$json['area'] = idSelect(array(
			"type"     => "option",
			"sqlForm"  => " region where province = '" . $data['post']['province'] . "' and city = '" . $data['post']['city'] . "' ",
			"sqlId"    => "id",
			"sqlField" => "area",
			"name"     => "area",
			"title"    => "区域",
		));
		return $json;
	}
	
	/*异步加载通用文章某段内容*/
	public function getArticleText($data)
	{
		$article      = query("article", " id = '" . $data['post']['articleId'] . "' ");
		$json['word'] = html_entity_decode($article['word'], ENT_QUOTES);
		return $json;
	}
	
	/*通用文章管理-新增或更新文字段落*/
	public function articleWordEdit($data)
	{
		//赋值
		$field = array(
			"type"       => $data['post']['type'],//文章分类
			"typeId"     => $data['post']['typeId'],//分类id
			"word"       => $data['post']['word'],//段落内容
			"updateTime" => date("Y-m-d H:i:s"),//更新时间
		);
		$id    = $data['post']['articleId'];//段落ID号
		//判断
		if (empty($field['type'])) {
			$json['warn'] = "文章分类为空";
		} elseif (empty($field['word'])) {
			$json['warn'] = "您还没有填写文字呢";
		} elseif (empty($id)) {
			$articleLast  = query("article", " typeId = '$field[typeId]' order by list desc ");
			$list         = $articleLast['list'] + 1;
			$id           = suiji();
			$field        = array_merge($field, array("id" => $id, "list" => $list, "time" => date("Y-m-d H:i:s")));
			$json['warn'] = insert(array("table" => "article", "field" => $field));
		} else {
			$json['warn'] = update(array("table" => "article", "field" => array("word" => $field['word'], "updateTime" => date("Y-m-d H:i:s")), "where" => " id = '$id' "));
		}
		//提示
		if (in_array($json['warn'], array("新增成功", "更新成功"))) {
			$_SESSION['warn'] = $json['warn'];
			$json['warn']     = 2;
		}
		//返回
		return $json;
	}
	
	/*通用文章管理-更新序列号*/
	public function articleListEdit($data)
	{
		//赋值
		$field   = array(
			"list"       => $data['post']['articleListText'],//排序号
			"updateTime" => date("Y-m-d H:i:s"),//更新时间
		);
		$article = query("article", " id = '" . $data['post']['artcleListId'] . "' ");//段落ID号
		if (empty($field['list'])) {
			$json['warn'] = "排序号不能为空";
		} elseif (preg_match(checkInteger, $field['list']) == 0) {
			$json['warn'] = "排序号必须为正整数";
		} elseif (empty($article['id'])) {
			$json['warn'] = "未找到此段落";
		} else {
			$json['warn'] = update(array("table" => "article", "field" => $field, "where" => " id = '$article[id]' "));
			//提示
			if ($json['warn'] == "更新成功") {
				$_SESSION['warn'] = $json['warn'];
				$json['warn']     = 2;
			}
		}
		//返回
		return $json;
	}
	
	/*通用文章管理-新增或更新图片*/
	public function articleImgEdit($data)
	{
		//判断
		if (empty($data['post']['type'])) {
			$warn = "文章分类为空";
		} elseif (empty($data['post']['typeId'])) {
			$warn = "未找到此记录";
		} elseif (empty($data['post']['folder'])) {
			$warn = "图片文件夹名称为空";
		} elseif (empty($data['post']['maxWidth'])) {
			$warn = "图片最大宽度为空";
		} else {
			$para = array(
				"fileName" => "imgFile",//上传图片的表单文件域名称
				"make"     => "缩放图像",//处理方式：裁剪图像、缩放图像、空
				"field"    => "img",//存放图片根目录的数据库字段名
				
				"maxNum"    => 100,//新增图像时限定的图像总数
				"newWidth"  => $data['post']['maxWidth'],//新图像的宽度
				"newHeight" => "",//新图像的高度，图像裁剪时必须
				"maxHeight" => 5000,//缩放后图片的最大高度
			);
			//拼接新图片保存的网站根目录位置
			$para['url'] = "img/articleImg/" . $data['post']['folder'];
			if (!file_exists(serverRoot . $para['url'])) {
				mkdir(serverRoot . $para['url']);
			}
			$para['url'] .= "/" . suiji() . ".jpg";
			//判断是新增图像还是更新图像
			if (empty($data['post']['id'])) {
				$para['type']      = "新增图像";                                                                                 //插入类型：更新图像、新增图像
				$para['sqlSearch'] = "select * from article where typeId = '" . $data['post']['typeId'] . "' and word = '' ";    //查询图片的数据库代码
				$lastArticle       = query("article", " typeId = '" . $data['post']['typeId'] . "' order by list desc");
				$newList           = $lastArticle['list'] + 1;
				$articleId         = suiji();
				$anchor            = "#" . $articleId;
				//数据库图片处理代码
				$field         = array(
					"id"           => $articleId,
					"type"         => $data['post']['type'],
					"typeId"       => $data['post']['typeId'],
					$para['field'] => $para['url'],
					"list"         => $newList,
					"updateTime"   => date("Y-m-d H:i:s"),
					"time"         => date("Y-m-d H:i:s"),
				);
				$para['sqlIn'] = array("table" => "article", "field" => $field);
			} else {
				$para['type']      = "更新图像";
				$para['sqlSearch'] = " select * from article where id = '" . $data['post']['id'] . "' ";
				$para['sqlIn']     = array("table" => "article", "field" => array($para['field'] => $para['url'], "updateTime" => date("Y-m-d H:i:s")), "where" => " id = '" . $data['post']['id'] . "' ");
				$anchor            = "#" . $data['post']['id'];
			}
			$warn             = imgUpdate($para);
			$_SESSION['warn'] = $warn;
			header("location:" . getenv("HTTP_REFERER") . $anchor);
			exit(0);
		}
	}
	
	/*通用文章管理-删除段落*/
	public function articleDelete($data)
	{
		//赋值
		$article = query("article", " id = '" . $data['get']['id'] . "' ");
		//判断
		if (empty($data['get']['id'])) {
			$_SESSION['warn'] = "段落ID号为空";
		} elseif (empty($article['id'])) {
			$_SESSION['warn'] = "未找到此段落";
		} else {
			//删除图片
			fileDelete($article['img']);
			//删除数据库记录
			delete(array("table" => "article", "where" => " id = '$article[id]' "));
			//返回信息
			$_SESSION['warn'] = "本段内容删除成功";
			//跳转
			$articleList = $article['list'] - 1;
			$lastArticle = query("article", " typeId = '$article[typeId]' and list = '$articleList' ");
			$anchor      = "#" . $lastArticle['id'];
			header("location:" . getenv("HTTP_REFERER") . $anchor);
			exit(0);
		}
	}
	
	/*图形验证码*/
	public function proveImg()
	{
		header("content-type:image/png");
		$image_width  = 100;
		$image_height = 37;
		$new_number   = "1234567890";
		$num_image    = imagecreate($image_width, $image_height);
		imagecolorallocate($num_image, 255, 255, 255);
		$str = "";
		for ($i = 0; $i < 4; $i++) {
			//随机字体
			$font   = mt_rand(3, 5);
			$x      = mt_rand(1, 8) + $image_width * $i / 4;
			$y      = mt_rand(1, $image_height / 4);
			$color  = imagecolorallocate($num_image, mt_rand(0, 200), mt_rand(0, 150), mt_rand(0, 200));
			$number = $new_number[rand(0, 9)];
			$str    .= $number;
			$x1     = mt_rand(1, 32);
			$y1     = mt_rand(1, 32);
			imagestring($num_image, $font, $x, $y, $number, $color);
			imageline($num_image, $x1, $y1, $x, $y, $color);//画干扰线
		}
		$_SESSION["yan"] = $str;
		imagepng($num_image);
		imagedestroy($num_image);
		exit();
	}
	
	/*返回*/
	public function html($data)
	{
		//判断主体
		$type = $data['get']['type'];
		if (!method_exists(__CLASS__, $type)) {
			$json['warn'] = "未知执行指令";
		} else {
			$json = $this->$type($data);
		}
		//返回
		return json_encode($json, 320);
	}
	
	/**
	 * 备份函数
	 *
	 * @return void
	 */
	public function automatic()
	{
		if (para("automatic") !== date("Ymd")) {
			//更新处理日期
			paraEdit("automatic", date("Ymd"));
			// 备份数据库
			$this->backUp();
			//还原数据库
			//$this->mySqlRestore($data);
		}
	}
	
	private static function addFileToZip($path, $zip)
	{
		$handler = opendir($path);
		while (($filename = readdir($handler)) !== false) {
			//文件夹文件名字为'.'和‘..'，不要对他们进行操作
			if ($filename != "." && $filename != "..") {
				// 如果读取的某个对象是文件夹，则递归
				if (is_dir($path . "/" . $filename)) {
					self::addFileToZip($path . "/" . $filename, $zip);
				} else {
					$zip->addFile($path . "/" . $filename, basename($filename));
				}
			}
		}
		@closedir($handler);
	}
	
	private function backUp()
	{
		$newUrl = "backups/" . date('Ymd');
		if (file_exists($newUrl) === false) {
			//如果根目录不存在存放数据库文件的文件夹，则创建
			if (!file_exists($newUrl)) {
				self::_mkdir($newUrl);
			}
			//将最新的数据库保存到新建的文件夹中
			$this->dataBackup($newUrl);
			// 打包
			$zip     = new ZipArchive();
			$dirPath = '../' . $newUrl;
			$zipPath = serverRoot . $newUrl . '_' . uniqid() . '.zip';
			if ($zip->open($zipPath, ZipArchive::CREATE) === true) {
				self::addFileToZip($dirPath, $zip);
				$zip->close();
				// 删除文件
				self::deleteFile($dirPath);
			}
			//删除超过30天的文件夹
			$fileArray = glob(serverRoot . "backups/*");
			$starTime  = strtotime(date("Ymd")) - 3600 * 24 * 30;
			foreach ($fileArray as $filePath) {
				$fileMtime = filemtime($filePath);
				if ($fileMtime < $starTime) {
					unlink($filePath);
				}
			}
		}
	}
	
	/**
	 * 备份主函数
	 *
	 * @param string $path 要备份的路径
	 */
	private static function dataBackup($path)
	{
		global $con;
		$res = mysqli_query($con, "SHOW TABLES");
		while ($row = mysqli_fetch_array($res)) {
			self::backupTable($row[0], $path);
		}
		mysqli_free_result($res);
		mysqli_close($con);
	}
	
	/**
	 * 备份表
	 *
	 * @param string $table 数据表名
	 * @param string $path  要备份的路径
	 */
	private static function backupTable($table, $path)
	{
		global $con;
		$data = '';
		$file = serverRoot . $path . '/' . $table . ".sql"; //存放路径
		//构造表结构语句
		$res  = mysqli_query($con, "SHOW CREATE TABLE `$table` ");
		$row  = mysqli_fetch_array($res);
		$data .= $row['Create Table'] . ";\r\n";
		//构造插入数据语句
		$res2 = mysqli_query($con, "SELECT * FROM `$table` ");
		while ($arr = mysqli_fetch_assoc($res2)) {
			$keys = array_keys($arr);
			$keys = array_map('addslashes', $keys);
			$keys = join('`,`', $keys);
			$keys = "`" . $keys . "`";
			$val  = array_values($arr);
			$val  = array_map('addslashes', $val);
			$val  = join("','", $val);
			$val  = "'" . $val . "'";
			$data .= "INSERT IGNORE INTO `$table`($keys) VALUES ($val);\r\n";
		}
		$bool = file_put_contents($file, $data);
		if (!$bool) {
			test("$table 备份失败" . mysqli_error() . $file);
		}
	}
	
	/**********文件夹删除函数*********************************/
	private static function deleteFile($url)
	{
		//先删除目录下的文件：
		if ($old = opendir($url)) {
			while (($file = readdir($old)) !== false) {
				if ($file != "." && $file != "..") {
					$path = "{$url}/{$file}";
					if (is_dir($path)) {
						self::deleteFile($path);
					} else {
						unlink($path);
					}
				}
			}
			closedir($old);
		}
		//删除当前文件夹：
		if (rmdir($url)) {
			return "deleteFile Yes";
		} else {
			return "deleteFile No";
		}
	}
	
	/**
	 * 报工端登录
	 *
	 * @param array $data
	 * @return array
	 */
	public function reportLogin(array $data): array
	{
		if (empty($data['post']['company'])) {
			$json['warn'] = "请输入企业名称";
		} elseif (empty($data['post']['userName'])) {
			$json['warn'] = "请输入用户名";
		} elseif (preg_match(checkString, $data['post']['userName']) == 0) {
			$json['warn'] = "用户名格式有误";
		} elseif (empty($data['post']['password'])) {
			$json['warn'] = "请输入登录密码";
		} elseif (strlen($data['post']['password']) < 6 || strlen($data['post']['password']) > 20) {
			$json['warn'] = "登录密码不得低于六位或大于20位";
		} elseif (empty($data['post']['did'])) {
			$json['warn'] = "登录设备异常";
		} else {
			$password = $data['post']['password'];
			
			$company    = query("company", " name = '" . $data['post']['company'] . "' ", "coid,name");
			$user       = query("user", " userName = '" . $data['post']['userName'] . "' ");
			$adLoginNum = para("adLoginNum");//每日登录密码最大的错误次数
			if (empty($company['coid'])) {
				$json['warn'] = "企业【" . $data['post']['company'] . "】不存在";
			} elseif (empty($user['userName'])) {
				$json['warn'] = "用户名【" . $data['post']['userName'] . "】不存在";
			} elseif ($user['loginError'] >= $adLoginNum and $user['loginErrorDay'] == date("Y-m-d")) {
				$json['warn'] = "您今天登录密码输入错误次数已经超过" . $adLoginNum . "次，不能再登录了";
			} elseif ($user['state'] == "停用") {
				$json['warn'] = "您的账号处于停用状态，请联系行政人员！";
			} //登录密码输入错误
			elseif (verifyPwd($password, $user['password']) !== true) {
				if (isset($_SESSION['forgetPas']) && $data['post']['userName'] == $_SESSION['forgetPas']['name'] and verifyPwd($password, $_SESSION['forgetPas']['prove'])) {
					//如果是点击忘记密码时发送到手机上的短信验证码
					update([
						"table" => "user",
						"field" => [
							"password"   => md5s($data['post']['password']),
							"updateTime" => date("Y-m-d H:i:s"),
						],
						"where" => " userName = '" . $data['post']['userName'] . "' ",
					]);
					unset($_SESSION['forgetPas']['prove']);
					$json['warn'] = 2;
				} else {
					if ($user['loginError'] >= $adLoginNum) {
						$user['loginError'] = 0;
					}
					$num    = $user['loginError'] + 1;
					$remain = $adLoginNum - $num;//今天还能登录的次数
					update([
						"table" => "user",
						"field" => [
							"loginError"    => $num,
							"loginErrorDay" => date("Y-m-d"),
							"updateTime"    => date("Y-m-d H:i:s"),
						],
						"where" => " userName = '" . $data['post']['userName'] . "' ",
					]);
					$json['warn'] = "登录密码错误，您今天还可以登录" . $remain . "次";
				}
			} else {
				$json['warn'] = 2;
			}
			if ($json['warn'] == 2) {
				$this->rSet($user['uid'] . 'loginPage', 1);
				//登录密码错误次数清零
				update([
					"table" => "user",
					"field" => [
						'deviceId'   => $data['post']['did'],
						'loginError' => 0,
					],
					"where" => " userName = '" . $data['post']['userName'] . "' ",
				]);
				//添加登录记录
				insert([
					"table" => "log",
					"field" => [
						"type" => "user",
						"stid" => $user['stid'],
						"text" => $user['name'] . "登录了管理员后台，ip地址：" . getIp(),
						"time" => date("Y-m-d H:i:s"),
					],
				]);
				//创建登录session，返回跳转地址
				$_SESSION['stid']     = $user['stid'];
				$_SESSION['deviceId'] = $data['post']['did'];
				$_SESSION['coid']     = $company['coid'];
				$json['href']         = root . "control/pad.html";
			}
		}
		return $json;
	}
}

//实例化对象
$libData = new libDataClass();
//打印结果
echo $libData->html(array("get" => $get, "post" => $post, "dataBase" => $conf));
